package com.youyi.utils;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.TemporalUnit;
import java.util.concurrent.ConcurrentHashMap;

public class LocalDateTimeUtil {

    // Thread-safe cache for DateTimeFormatter to improve performance.
    private static final ConcurrentHashMap<String, DateTimeFormatter> formatterCache = new ConcurrentHashMap<>();

    /**
     * 获取当前的 LocalDateTime。
     *
     * @return 当前的 LocalDateTime 实例。
     */
    public static LocalDateTime now() {
        return LocalDateTime.now();
    }

    /**
     * 将 LocalDateTime 格式化为指定模式的字符串。
     *
     * @param localDateTime 要格式化的 LocalDateTime 对象。
     * @param pattern       格式化模式。
     * @return 格式化后的日期时间字符串。
     */
    public static String format(LocalDateTime localDateTime, String pattern) {
        DateTimeFormatter formatter = formatterCache.computeIfAbsent(pattern, DateTimeFormatter::ofPattern);
        return localDateTime.format(formatter);
    }

    /**
     * 解析字符串为 LocalDateTime。
     *
     * @param dateStr 字符串形式的日期时间。
     * @param pattern 解析模式。
     * @return 解析后的 LocalDateTime 对象。
     */
    public static LocalDateTime parse(String dateStr, String pattern) {
        DateTimeFormatter formatter = formatterCache.computeIfAbsent(pattern, DateTimeFormatter::ofPattern);
        return LocalDateTime.parse(dateStr, formatter);
    }

    /**
     * 在给定的 LocalDateTime 上加上指定的时间段。
     *
     * @param localDateTime 原始的 LocalDateTime 对象。
     * @param amountToAdd   要添加的时间数量。
     * @param unit          时间单位（ChronoUnit）。
     * @return 添加后的新 LocalDateTime 对象。
     */
    public static LocalDateTime plus(LocalDateTime localDateTime, long amountToAdd, TemporalUnit unit) {
        return localDateTime.plus(amountToAdd, unit);
    }

    /**
     * 在给定的 LocalDateTime 上减去指定的时间段。
     *
     * @param localDateTime 原始的 LocalDateTime 对象。
     * @param amountToSubtract 要减去的时间数量。
     * @param unit          时间单位（ChronoUnit）。
     * @return 减去后的新 LocalDateTime 对象。
     */
    public static LocalDateTime minus(LocalDateTime localDateTime, long amountToSubtract, TemporalUnit unit) {
        return localDateTime.minus(amountToSubtract, unit);
    }

    /**
     * 获取某月的第一天，时间为00:00。
     *
     * @param year  年份。
     * @param month 月份。
     * @return 某月第一天的 LocalDateTime 对象。
     */
    public static LocalDateTime getFirstDayOfMonth(int year, int month) {
        return YearMonth.of(year, month).atDay(1).atStartOfDay();
    }

    /**
     * 获取某月的最后一天，时间为23:59:59.999999999。
     *
     * @param year  年份。
     * @param month 月份。
     * @return 某月最后一天的 LocalDateTime 对象。
     */
    public static LocalDateTime getLastDayOfMonth(int year, int month) {
        return YearMonth.of(year, month).atEndOfMonth().atTime(LocalTime.MAX);
    }

    /**
     * 获取两个 LocalDateTime 之间的差值，以指定的时间单位返回。
     *
     * @param startInclusive 开始时间（包含）。
     * @param endExclusive   结束时间（不包含）。
     * @param unit           时间单位（ChronoUnit）。
     * @return 时间差值。
     */
    public static long between(LocalDateTime startInclusive, LocalDateTime endExclusive, TemporalUnit unit) {
        return unit.between(startInclusive, endExclusive);
    }

    /**
     * 判断给定的 LocalDateTime 是否在指定的两个时间之间。
     *
     * @param timeToCheck      要检查的 LocalDateTime。
     * @param startTimeInclusive 开始时间（包含）。
     * @param endTimeExclusive   结束时间（不包含）。
     * @return 如果给定时间在指定范围内，则返回 true；否则返回 false。
     */
    public static boolean isBetween(LocalDateTime timeToCheck, LocalDateTime startTimeInclusive, LocalDateTime endTimeExclusive) {
        return !timeToCheck.isBefore(startTimeInclusive) && timeToCheck.isBefore(endTimeExclusive);
    }

    /**
     * 判断给定的 LocalDateTime 是否是属于今天的时间
     * @param time 判断的日期对象
     * @return 是 则返回 true 否 则返沪 false
     */
    public static boolean isToday(LocalDateTime time){
        LocalDateTime nowTime = LocalDateTime.now();
        return time.getYear() == nowTime.getYear() && time.getMonth() == nowTime.getMonth() && time.getDayOfMonth() == nowTime.getDayOfMonth();
    }


    // 更多功能可以在此基础上添加，如计算工作日、节假日等特殊逻辑。
}